# service/recording.py
import logging
from abc import ABC, abstractmethod
from fastapi import Request, UploadFile, BackgroundTasks
import sqlalchemy as sa
import pydantic
from fastapi_pagination.ext.databases import paginate

from admin.schemas.meetings_recording import MeetingsRecordingListIn, MeetingsRecordingAddIn, MeetingsRecordingEditIn, \
    MeetingsRecordingOut
from admin.service.base_service import BaseService
from plugins.storage.storage_driver import StorageDriver
from schema_base import PageInationResult
from utils.db_operate import generate_query_conditions
from transcribe_worker import transcribe_recording
from models import meetings

logger = logging.getLogger(__name__)


class IMeetingsRecordingService(ABC):
    @abstractmethod
    async def list(self, list_in: MeetingsRecordingListIn) -> PageInationResult[MeetingsRecordingOut]:
        pass

    @abstractmethod
    async def detail(self, id_: int) -> MeetingsRecordingOut:
        pass

    @abstractmethod
    async def upload_file(self, meeting_id: int, file: UploadFile, background_tasks: BackgroundTasks = None):
        pass

    @abstractmethod
    async def edit(self, edit_in: MeetingsRecordingEditIn):
        pass

    @abstractmethod
    async def delete(self, id_: int):
        pass


class MeetingsRecordingService(IMeetingsRecordingService, BaseService):
    tableModel = meetings.MeetingsRecording.__table__

    def __init__(self, request: Request):
        super().__init__(request)

    @classmethod
    async def instance(cls, request: Request):
        return cls(request)

    async def list(self, list_in: MeetingsRecordingListIn):
        where = generate_query_conditions(list_in, self.tableModel)
        q = sa.select(self.tableModel).where(*where).select_from(self.tableModel).order_by(
            self.tableModel.c.uploaded_at.desc())
        res = await paginate(self.conn, q)
        return res

    async def detail(self, id_: int):
        model = await self.conn.fetch_one(self.tableModel.select().where(self.tableModel.c.id == id_).limit(1))
        assert model, "录音不存在"
        return MeetingsRecordingOut.from_orm(model)

    async def upload_file(self, meeting_id: int, file: UploadFile, background_tasks: BackgroundTasks = None):
        file_type = 20
        result = await StorageDriver.upload(file, 'video', file_type, 'local')
        rec = {"meeting_id": meeting_id, 'url': result['url'], "filename": file.filename,
               "processing_status": "uploaded", "file_type": file_type, "ext": result['ext'], }
        res = await self.conn.execute(self.tableModel.insert().values(rec))
        rec_id = getattr(res, "lastrowid", None)
        if background_tasks:
            background_tasks.add_task(transcribe_recording, rec_id)
        else:
            transcribe_recording(rec_id)
        return {"id": rec_id}

    async def edit(self, edit_in: MeetingsRecordingEditIn):
        assert await self.conn.fetch_one(
            self.tableModel.select().where(self.tableModel.c.id == edit_in.id).limit(1)), "录音不存在"
        vals = edit_in.dict(exclude_none=True)
        vals.pop("id", None)
        await self.conn.execute(self.tableModel.update().where(self.tableModel.c.id == edit_in.id).values(vals))

    async def delete(self, id_: int):
        assert await self.conn.fetch_one(self.tableModel.select().where(self.tableModel.c.id == id_).limit(1)), "录音不存在"
        await self.conn.execute(self.tableModel.delete().where(self.tableModel.c.id == id_))
